<script>
import objectPath from 'object-path';

/**
 * @typedef {Object} SortProps
 * @property {string} name 当前排序字段（tableColums的sortName属性）
 * @property {'desc' | 'asc'} type 当前排序的类型，升序/降序
 */

/**
 * 属性说明
 *
 * @property {Array<any>} data 数据
 * @property {string} rowKey 循环使用的 key 所在 data 中的 key, 支持多级查询
 * @property {string} title title
 * @property {string} subtitle subtitle
 * @property {string} height 高度，超出后出现滚动条
 * @property {{ icon: string, message: string, iconWidth: string, iconHeight: string }} empty 启用空的占位
 * @property {SortProps} sort 当前排序的对象
 * @property {string} defaultValue 每个cell在渲染时 如果没有插槽并且对应的prop没有值(undefined | null)，渲染默认值，如果column上有设置，会覆盖此处的设置
 */

/**
 * 事件说明
 *
 * @selectionChange 选中项改变是触发，有该事件默认开启每行可选checkbox 参数 @see data[] (传入进来的data的部分项)
 * @sortChange 排序项改变时触发 参数 @see SortProps
 */

/**
 * 具名插槽
 *
 * title title插槽优先级高于props.title
 * filter 筛选插槽
 * filter-action 筛选的批量操作 有筛选项的时候并且有操作项显示
 * pagination 分页插槽
 * empty 代替默认的empty，并且优先级高于props.empty的配置
 */

import TableColumn from './_TableColumn';

export default {
  components: { TableColumn },
  data() {
    return {
      selected: [],
      selectAll: false,
      showSort: false,
      renderDefault: []
    };
  },
  props: {
    data: {
      type: Array,
      default() {
        return [];
      }
    },
    rowKey: { type: String, required: true },
    title: { type: String },
    subtitle: { type: String },
    height: { type: String, default: '100%' },
    empty: {
      type: Object,
      default() {
        return { icon: '', message: '', iconHeight: '' };
      }
    },
    sort: {
      type: Object,
      default() {
        return { name: '', type: '' };
      }
    },
    defaultValue: { type: String }
  },
  methods: {
    objectPath: objectPath.get,
    onSelectAllChange() {
      if (this.selectAll && !this.selectAllColumns) {
        this.selected.splice(0, this.selected.length, ...this.data);
      }
      if (!this.selectAll && this.selected.length) {
        this.selected.splice(0, this.selected.length);
      }
      this.$emit('selection-change', this.selected);
    },
    onSelectedChange() {
      if (!this.selected.length && this.selectAll) {
        this.selectAll = false;
      }
      if (this.selected.length && !this.selectAll) {
        this.selectAll = true;
      }
      this.$emit('selection-change', this.selected);
    },
    onTitleClick(sortName) {
      /** 不可排序，不处理 */
      if (!sortName) {
        return;
      }

      /** @type {SortProps} */
      const sortProp = { name: sortName, type: 'desc' };

      /** 如果是当前sort项，仅改变sort type */
      if (this.sort.name === sortName) {
        sortProp.type = this.sort.type === 'asc' ? 'desc' : 'asc';
      }
      this.$emit('sortChange', sortProp);
    },
    onTitleFocus(sortName) {
      /** 不可排序，不处理 */
      if (!sortName) {
        return;
      }
      /** 鼠标hover 显示排序*/
      this.showSort = sortName;
    },
    onTitleLeave(sortName) {
      /** 不可排序，不处理 */
      if (!sortName) {
        return;
      }
      /** 鼠标hover 显示排序*/
      this.showSort = '';
    }
  },
  computed: {
    /**
     * @description 过滤掉非EdoovoTableColumn的组件
     * @returns { elements } 非EdoovoTableColumn的组件
     */
    columns() {
      return (this.renderDefault || []).filter(
        component =>
          component.tag &&
          component.tag.endsWith('EdoovoTableColumn') &&
          component.data.key !== 'action'
      );
    },
    /**
     * @description action的列
     * @returns { elements } action的列
     */
    actionColums() {
      return (this.renderDefault || []).find(
        component =>
          component.tag &&
          component.tag.endsWith('EdoovoTableColumn') &&
          component.data.key === 'action'
      );
    },
    /**
     * @description 当前是否每一行都选中了
     * @returns { boolean } 是否每一行都选中了
     */
    selectAllColumns() {
      return this.data.every(item => this.selected.includes(item));
    }
  },
  watch: {
    data: {
      handler() {
        this.selectAll = false;
        this.selected.splice(0);
      }
    }
  },
  mounted() {
    this.renderDefault = this.$slots.default;
  },
  beforeUpdate() {
    this.renderDefault = this.$slots.default;
  }
};
</script>

<template lang="pug">
.edoovo-table-box(:style="{ height: height, 'padding-top': `${0 + (title || subtitle || $slots.title ? 64 : 0) + ($slots.filter && data.length ? 72 : 0)}px`, 'padding-bottom': `${$slots.pagination && data.length ? 52 : 0}px` }")
  .edoovo-table-head(v-if="title || subtitle || $slots.title")
    slot(name="title")
      .edoovo-table-head-titlebox
        h2(v-if="title") {{ title }}
        h3(v-if="subtitle") {{ subtitle }}

  .edoovo-table-filter(v-if="$slots.filter" :style="{ top: `${title || subtitle || $slots.title ? 64 : 0}px`, borderBottomWidth: (!data || !data.length) ? 0: '1px' }") #[slot(name="filter")]

  .edoovo-table-empty(v-if="!data.length")
    slot(name="empty" v-if="$slots.empty")
    template(v-else)
      i(:style="{ 'background-image': empty.icon ? `url(${empty.icon})` : '', height: empty.iconHeight, width: empty.iconWidth }")
      p {{empty.message || 'No data'}}

  template(v-else)

    .edoovo-table-filter-action(v-if="$slots['filter-action'] && selected.length") #[slot(name="filter-action")]

    .edoovo-table

      ul.edoovo-thead
        template(v-if="$listeners['selection-change'] && data.length")
          li.edoovo-table-cell.edoovo-table-selected-cell #[md-checkbox(v-model="selectAll" :indeterminate="selected.length !== data.length" @change="onSelectAllChange")]
        template(v-for="(cell, index) in columns")
          li.edoovo-table-cell(
            :style="{ width: cell.componentOptions.propsData.width }"
            :class="`edoovo-table-cell-size-${cell.componentOptions.propsData.size || 'M'} edoovo-table-cell-align-${cell.componentOptions.propsData.headerAlign || cell.componentOptions.propsData.align || 'left'} ${cell.componentOptions.propsData.sortName ? 'edoovo-table-sort-able' : ''} ${sort.name === cell.componentOptions.propsData.sortName ? 'edoovo-table-sorted' : ''} ${index === columns.length - 1 ? 'edoovo-table-cell-last' : ''}`"
            @click="onTitleClick(cell.componentOptions.propsData.sortName)"
            @mouseover="onTitleFocus(cell.componentOptions.propsData.sortName)"
            @mouseleave="onTitleLeave(cell.componentOptions.propsData.sortName)"
          )
            .edoovo-table-cell-inner {{ cell.componentOptions.propsData.label }}
            template(v-if="(cell.componentOptions.propsData.sortName && showSort === cell.componentOptions.propsData.sortName) || (cell.componentOptions.propsData.sortName&&sort.name === cell.componentOptions.propsData.sortName)")
              //- 默认全部向下，仅当前sort并且是升序，使用向上
              i.iconfont.iconarrow_upward-24px.edoovo-table-sort-icon(v-if="sort.name === cell.componentOptions.propsData.sortName && sort.type === 'asc'")
              i.iconfont.iconarrow_downward-24px.edoovo-table-sort-icon(v-else)
        li.edoovo-table-cell.edoovo-table-cell-flex1

      .edoovo-tbody
        ul.edoovo-tbody-row(
          v-for="(item, index) in data" :key="rowKey ? objectPath(item, rowKey) : index"
          :class="{ 'edoovo-tbody-row-selected': selected.includes(item) }"
        )
          template(v-if="$listeners['selection-change']")
            li.edoovo-table-cell.edoovo-table-selected-cell #[md-checkbox(v-model="selected" :value="item" @change="onSelectedChange")]
          template(v-for="(cell, index) in columns")
            li.edoovo-table-cell(
              :style="{ width: cell.componentOptions.propsData.width }"
              :class="`edoovo-table-cell-size-${cell.componentOptions.propsData.size || 'M'} edoovo-table-cell-align-${cell.componentOptions.propsData.align || 'left'} ${index === columns.length - 1 ? 'edoovo-table-cell-last' : ''}`"
            ) #[TableColumn(:data="item" :vnode="cell" :index="index" :defaultValue="defaultValue")]
          li.edoovo-table-cell.edoovo-table-cell-flex1
          li.edoovo-table-cell.edoovo-table-cell-action(
            v-if="actionColums"
            :style="{ width: actionColums.componentOptions.propsData.width }"
          ) #[TableColumn(:data="item" :vnode="actionColums")]

    .edoovo-table-pagination(v-if="$slots.pagination") #[slot(name="pagination")]
</template>

<style lang="stylus">
.edoovo-table-box
  position relative
  background-color #fff
  color rgba(32, 33, 36, .5)
  font-family Roboto
.edoovo-table-head
  font-family: OpenSans-Bold
  font-size 22px
  position absolute
  width 100%
  height 64px
  left 0
  top 0
  display flex
  align-items center
  padding 0 36px
  color #202124
  background #fff
  border-bottom 1px solid #e3e3e3
.edoovo-table-head-titlebox
  display flex
  flex-direction column
  justify-content center
  h2
    font-size 20px
    font-weight 600
  h3
    color #989898
    font-weight normal
    font-size 14px
    font-family OpenSans
    margin-top 3px
.edoovo-table-filter
  position absolute
  width 100%
  height 72px
  left 0
  top 0
  display flex
  align-items center
  padding 0 36px
  background #fff
  border-bottom 1px solid #e3e3e3
  &.no_bottom
    border-bottom-color: transparent
.edoovo-table-filter-action
  position absolute
  top 0
  left 0
  display flex
  align-items center
  height 64px
  width 100%
  z-index 10
  background-color #fff
  padding 0 32px
  &:after
    content ''
    position absolute
    width 100%
    height 100%
    left 0
    top 0
    background-color rgba(255,82,82,.2)
.edoovo-table
  height 100%
  overflow auto
  position relative
  z-index 1
.edoovo-table-cell
  display flex
  align-items center
  flex-shrink 0
  border-bottom 1px solid #e9e9e9
  padding 0 16px
  box-sizing border-box
  &.edoovo-table-selected-cell
    overflow hidden
  &.edoovo-table-cell-align-left
    justify-content flex-start
  &.edoovo-table-cell-align-right
    justify-content flex-end
  &.edoovo-table-cell-align-center
    justify-content center
  &.edoovo-table-cell-size-XXS-lesson
    width 22px
    padding 0 16px
  &.edoovo-table-cell-size-XS-lesson
    width 68px
    overflow visible
    text-overflow none
    padding 0 16px
  &.edoovo-table-cell-size-S-lesson
    width 100px
  &.edoovo-table-cell-size-M-lesson
    width 140px
  &.edoovo-table-cell-size-L-lesson
    width 220px
  &.edoovo-table-cell-size-XL-lesson
    width 312px
  &.edoovo-table-cell-size-XS
    width 68px
  &.edoovo-table-cell-size-S
    width 100px
  &.edoovo-table-cell-size-M
    width 140px
  &.edoovo-table-cell-size-L
    width 220px
  &.edoovo-table-cell-size-XL
    width 312px
.edoovo-table-cell-flex1
  padding 0
  flex 1
.edoovo-thead, .edoovo-tbody-row
  display flex
  flex-wrap nowrap
  .edoovo-table-cell:first-child
    padding-left 20px
  .edoovo-table-cell.edoovo-table-cell-last
    padding-right 36px
.edoovo-table-cell-action
  position sticky
  right 0
  width 0
  padding 0
  display none
  .edoovo-table-cell-inner
    position absolute
    height 100%
    top 0
    right 0
    display flex
    align-items center
    overflow visible
    > *:last-child
      margin-right 25px
.edoovo-table-cell-inner
  white-space nowrap
  text-overflow ellipsis
  word-break break-all
  overflow hidden
.edoovo-table-cell-inner.id
  font-family: Roboto;
  font-weight: 500;
  color: #1a73e8;
  cursor: pointer;
.edoovo-thead
  position sticky
  font-family Roboto-Medium
  top 0
  height 56px
  font-size 12px
  z-index 10
  .edoovo-table-cell
    background-color #F2F2F2
.edoovo-table-sort-icon
  display flex
  width 16px
  height 16px
  font-size 16px
  line-height 16px
  align-items center
  justify-content start
  margin-left 2px
.edoovo-table-sort-able
  cursor pointer
  transition color 120ms
  &.edoovo-table-sorted
    color #202124
  &:hover
    .edoovo-table-cell-inner
      color #202124
.edoovo-tbody
  font-size 13px
  font-family Roboto
.edoovo-tbody-row
  height 48px
  transition background-color 80ms
  &.edoovo-tbody-row-selected
    .edoovo-table-cell, .edoovo-table-cell-inner
      background-color #f5f5f5
  &:hover
    .edoovo-table-cell, .edoovo-table-cell-inner
      background-color #EEEEEE
    .edoovo-table-cell-action
      display block
.edoovo-table-pagination
  position absolute
  left 0
  bottom 0
  width 100%
  height 52px
  display flex
  align-items center
  background #fff
  padding-left 20px
  padding-right 20px
.edoovo-table-empty
  width 100%
  height 100%
  display flex
  flex-direction column
  align-items center
  justify-content center
  padding 50px 32px
  > i
    width 371px
    height 248px
    background url('./empty.png') no-repeat center / cover;
  > p
    margin-top 8px
    text-align  center
    font-size 22px
    line-height 30px
    font-family Roboto
    white-space: pre-wrap
    color #5F6368
.edoovo-table-cell-tooltip.el-tooltip__popper
  background #fff
  border 1px solid #707070
  color #5F6368
  max-width 500px
  line-height 13px
  padding 5px 9px 4px
  margin-top 7px
  border-radius 0
  font-family Roboto
  font-size 10px
.edoovo-table-cell-tooltip.el-tooltip__popper.is-dark
  background #6F6F6F
  border none
  color #FFFFFF
  border-radius 2px
.edoovo-table-cell-action .gg_submit_button:not(.is-disabled):hover
  color: #1A73E8;
  background: #d5dced;
</style>
